/*
 * mftgtexture.h
 *
 * This class encapsulates the datastructure and functionality of Textures
 * rendered by the Multi-Field Texture Grammar technique. See SimpleTexture
 * and StreamlineTexture.
 *
 *  Created on: 10/08/2012
 *      Author: cvan680
 */

#ifndef MFTGTEXTURE_H_
#define MFTGTEXTURE_H_

#include <string>
#include <iostream>
#include "modules/flowreen/utils/flowmath.h"
#include "modules/flowreen/datastructures/volumeflow3d.h"
#include "modules/flowreen/datastructures/flow2d.h"
#include "modules/flowreen/datastructures/flow3d.h"
#include "tgt/vector.h"
#include <typeinfo>

using namespace std;

namespace voreen {

// TODO
// 	should save pixel values probably in a 4-channel float array? (rgba).
//	should probably return a Texture element

class MFTGTexture {

public:

	// TODO do I need this? not sure of its purpose in SimpleTexture.
	//typedef T ElemType;

	// struct to return both the rgba data and the counter value
    struct MFTGTextureElement {
    	MFTGTextureElement(float& r, float& g, float& b, float& a, int& counter)
            : r_(r), g_(g), b_(b), a_(a), counter_(counter)
        {}

    	// TODO have accessors for all 4 channels? or do we just access by .a_
        //operator T() { return elem_; }

    	float& r_;
    	float& g_;
    	float& b_;
    	float& a_;
        int& counter_;
    };

public:

    enum SliceAlignment {
    	// :-)
        PLANE_XY = 2,   /** view from the volume's front to back (negative z-axis) */
        PLANE_XZ = 1,   /** view from the volume's bottom to top (negative y-axis) */
        PLANE_ZY = 0    /** view from the volume's right to left (negative x-axis) */
    };

    MFTGTexture(const tgt::ivec2 dimensions);
    MFTGTexture(const tgt::ivec3& dimensions);

    virtual ~MFTGTexture();

    virtual void free();

    void run();

    const float* getData() const { return data_; }
    const tgt::ivec3 getDimensions() const { return dimensions_; }
    int getNumElements() const { return numElements_; }

    const MFTGTexture::MFTGTextureElement operator[](int index) const;
    const MFTGTexture::MFTGTextureElement operator[](const tgt::ivec2& position) const;
    const MFTGTexture::MFTGTextureElement operator[](const tgt::ivec3& position) const;

    MFTGTexture::MFTGTextureElement operator[](int index);
    MFTGTexture::MFTGTextureElement operator[](const tgt::ivec2& position);
    MFTGTexture::MFTGTextureElement operator[](const tgt::ivec3& position);

    void loadTextureGrammar(string filename);
//    const void loadTextureGrammar(TextureGrammar grammar) const { grammar_ = grammar; }

    void loadVolume(const VolumeBase* volume);
    void loadVolumeCollection(VolumeCollection* collection);


    /* Texturing algorithms */
	/* FIXME why were these static? */
    /* FIXME remove volumes from parameters - they need to be loaded through methods */
    void MFTGTexture::fastLIC(const Flow3D& flow3D1, const Flow3D& flow3D2);
    void multiLIC();


    tgt::Texture* MFTGTexture::colourLIC();

/*
    static float MFTGTexture::fastLICIntensity( const SimpleTexture<float>& inputTexture,
                           	   	   	    		const int indexR0,
                           	   	   	    		const int kernelSize,
                           	   	   	    		const std::vector<tgt::ivec2>& streamline );*/
    static float MFTGTexture::fastLICIntensity(  );


    float* MFTGTexture::scalarSliceToIntensity( const VolumeRAM* volram,
    											int sliceID,
    											tgt::ivec2 textureDimensions,
    											int scaling,
    											int alignment );

    tgt::Texture* MFTGTexture::scalarSliceToIntensityTexture( const VolumeRAM* volram,
    														  int sliceID,
    														  tgt::ivec2 textureDimensions,
    														  int scaling,
    														  int alignment );

    tgt::Texture* getTexture();


protected:
    int MFTGTexture::positionToIndex(const tgt::ivec2& position) const;
    int MFTGTexture::positionToIndex(const tgt::ivec3& position) const;

private:
    // x, y and z dimensions of this texture (z = 1 if 2d texture)
    const tgt::ivec3 dimensions_;

    // number of elements
    const int numElements_;

    // holds all the data information (per pixel 4 channels)
    float* const data_;

    int* counter_;

    // we use 4 channels for RGBA
    static const int NUM_CHANNELS = 4;

    vector<const VolumeBase*> volumes_;

    //TextureGrammar grammar_;
};

}

#endif /* MFTGTEXTURE_H_ */
